package br.com.virtual.base.validator;

import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import br.com.virtual.cadastrar.model.PessoaFisica;
import br.com.virtual.cadastrar.service.PessoaFisicaService;

/**
 * Por utilizar @Inject, deve possuir a annotation @ManagedBean ao inv�s de
 * 
 * @FacesValidator.
 */
@ManagedBean(name = "cpfValidator")
@RequestScoped
public class CPFValidator implements Validator {

	@EJB
	private PessoaFisicaService pessoaFisicaService;

	@Override
	public void validate(FacesContext context, UIComponent component,
			Object valorTela) throws ValidatorException {

		if (!validaCPF(String.valueOf(valorTela))) {
			throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "",
					"CPF Inválido, verifique o número e tente novamente."));
		}

		PessoaFisica pessoaFisica = pessoaFisicaService.findByCPF(String
				.valueOf(valorTela));
		// Verifica se o CPF já existe no banco de dados, se existe, retorna
		// erro
		if (pessoaFisica != null) {
			Long idEditando = (Long) component.getAttributes().get("idPessoa");

			if (!pessoaFisica.getId().equals(idEditando)) {
				throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "",
						"O CPF digitado já foi cadastrado."));
			}
		}
	}

	private boolean validaCPF(String cpf) {

		if (cpf == null || cpf.length() != 11)
			return false;

		try {
			Long.parseLong(cpf);
		} catch (NumberFormatException e) {
			return false;
		}

		if (isCPFPadrao(cpf))
			return false;

		return calculaDigitoVerificador(cpf.substring(0, 9)).equals(
				cpf.substring(9, 11));
	}

	private String calculaDigitoVerificador(String num) {

		Integer primeiro, segundo;
		int soma = 0, peso = 10;

		for (int i = 0; i < num.length(); i++) {
			soma += Integer.parseInt(num.substring(i, i + 1)) * peso--;
		}

		if (soma % 11 == 0 | soma % 11 == 1) {
			primeiro = 0;
		} else {
			primeiro = 11 - (soma % 11);
		}
		soma = 0;
		peso = 11;

		for (int i = 0; i < num.length(); i++)
			soma += Integer.parseInt(num.substring(i, i + 1)) * peso--;

		soma += primeiro.intValue() * 2;

		if (soma % 11 == 0 | soma % 11 == 1) {
			segundo = 0;
		} else {
			segundo = 11 - (soma % 11);
		}
		return primeiro.toString() + segundo.toString();

	}

	private boolean isCPFPadrao(String cpf) {

		if (cpf.equals("99999999999") || cpf.equals("88888888888")
				|| cpf.equals("77777777777") || cpf.equals("66666666666")
				|| cpf.equals("55555555555") || cpf.equals("44444444444")
				|| cpf.equals("33333333333") || cpf.equals("22222222222")
				|| cpf.equals("11111111111") || cpf.equals("00000000000"))
			return true;

		return false;

	}

}
